<script lang="ts">
import type { PropType } from "vue";
import { h } from "vue";
import { useRouter } from "vue-router";
import { ElMenu, ElSubMenu, ElMenuItem } from "element-plus";

export interface MenuItemData {
  title: string;
  path: string;
  children?: MenuItemData[];
}

export default {
  props: {
    menuData: Array as PropType<MenuItemData[]>,
    mode: String,
    backgroundColor: String,
    textColor: String,
    activeTextColor: String,
    defaultActive: String,
    onSelect: Function as PropType<(key, keyPath) => void>,
  },
  setup(props) {
    const router = useRouter();

    let lastClick = {} as MouseEvent;

    document.documentElement.addEventListener(
      "click",
      (event) => (lastClick = event)
    );

    const viewTransition = (key) => {
      // 获取点击位置，或者回退到屏幕中间
      const x = lastClick?.clientX ?? innerWidth / 2;
      const y = lastClick?.clientY ?? innerHeight / 2;
      // 获取到最远角的距离
      const endRadius = Math.hypot(
        Math.max(x, innerWidth - x),
        Math.max(y, innerHeight - y)
      );

      // 开始一次视图过渡：
      const doc: any = document
      const transition = doc.startViewTransition(() => {
        router.push(key);
      });

      // 等待伪元素创建完成：
      transition.ready.then(() => {
        // 新视图的根元素动画
        document.documentElement.animate(
          {
            clipPath: [
              `circle(0 at ${x}px ${y}px)`,
              `circle(${endRadius}px at ${x}px ${y}px)`,
            ],
          },
          {
            duration: 1000,
            easing: "ease-in",
            iterations: 1,
            // 指定要附加动画的伪元素
            pseudoElement: "::view-transition-new(root)",
          }
        );
      });
    };

    const createMenuItems = (array, parentIndex) => {
      const menuItems = [];

      for (const i in array) {
        const item = array[i];
        const index = parentIndex
          ? parentIndex + "-" + (+i + 1)
          : String(+i + 1);

        if (item.children)
          menuItems[i] = h(
            ElSubMenu,
            { index: item.path },
            {
              title: () => item.title,
              default: () => createMenuItems(item.children, index),
            }
          );
        else
          menuItems[i] = h(
            ElMenuItem,
            {
              index: item.path,
            },
            { default: () => item.title }
          );
      }

      return menuItems;
    };

    return () =>
      h(
        ElMenu,
        {
          mode: (props.mode as any) ?? "horizontal",
          backgroundColor: props.backgroundColor ?? "#06b",
          textColor: props.textColor ?? "#fff",
          activeTextColor: props.activeTextColor ?? "#0ff",
          defaultActive: props.defaultActive ?? "/",
          onSelect: (key, keyPath) => {
            props.onSelect?.(key, keyPath);
            viewTransition(key);
          },
        },
        {
          default: () => createMenuItems(props.menuData, null),
        }
      );
  },
};
</script>

<style>
::view-transition-image-pair(root) {
  isolation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
  display: block;
}
</style>
